#include "sys.h"
#include "iwdg.h"
#include "stm32f429xx.h"
#include "at24cxx.h"
#include "my_malloc.h"

uint32_t currentTick = 0; // 定义变量 记录系统运行时间
bool enterSleep = false;
/* 
 * memUsed[3]:
 * 0:内部内存使用率
 * 1:外部内存使用率
 * 2:CCM内存使用率
 */
uint16_t memUsed[3] = {0}; // 内存利用率
/* errorCode:[7:0]
 * 0:at24c02故障
 * 1:w25q256故障
 * 2:sdram故障
 * 3:nand ftl故障
 * 4:
 * 5:
 * 6:
 * 7:
 */
uint8_t errorCode = 0; // 故障字

void softReset(void) {
    __set_FAULTMASK(1); // 防止中断打断重置流程
    SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
    while (1); // 确保复位操作完成
}

void SysTick_Handler(void) { // SysTick中断
    currentTick++; // 增加系统运行时间记录
}

void sysProc(uint32_t currentTick) { // 调整系统
    static uint32_t oldTick = 0;
    if(currentTick - oldTick > 10000) { // 每10秒
        IWDG_FEED; // 喂狗
        if(enterSleep) { // 如果需要进入Standby
            enterSleep = false; // 去除进入标志
            AT24CXX_WriteOneByte(0x05, 0xAA); // 写入进入stanby标志
            /* 备份数据开始 */
            ;
            /* 备份数据结束 */
            softReset(); // 软件复位
        }
        // 统计内存使用率
        memUsed[0] = my_mem_perused(SRAMIN);
        memUsed[1] = my_mem_perused(SRAMEX);
        memUsed[2] = my_mem_perused(SRAMCCM);
        // 更新计时
        oldTick = currentTick;
    }
}

void wkupInit(void) {
    // 使能PWR和SYSCFG时钟
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
    // 配置PA0为输入模式，并设置为下拉
    GPIOA->MODER &= ~(GPIO_MODER_MODE0_Msk); // 输入模式
    GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD0_Msk); // 清除PA0的上拉/下拉配置位
    GPIOA->PUPDR |= (GPIO_PUPDR_PUPD0_0); // 设置PA0为下拉模式
    PWR->CSR |= PWR_CSR_EWUP; // 使能 PA0 作为唤醒引脚
}

void enterStandbyMode(void) {
    PWR->CR |= PWR_CR_CWUF; // 清除唤醒标志
    PWR->CR |= PWR_CR_PDDS; // 设置 PDDS 位，选择待机模式
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // 设置深度睡眠模式
    __WFI(); // 进入待机模式，任意中断唤醒
}
